package web.controller.admin;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.jfinal.aop.Before;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.ehcache.CacheKit;

import cn.dreampie.shiro.core.ShiroMethod;
import core.Const;
import kit.EhCacheKit;
import kit.Secure;
import kit.StringUtil;
import plugin.shiro.ClearShiro;
import plugin.shiro.ShiroKit;
import web.common.BaseController;
import web.common.JsonEntity;
import web.common.enums.ResultCodeEnum;
import web.interceptor.AdminLoginLogInterceptor;
import web.model.AdminPerm;
import web.model.AdminRole;
import web.model.AdminUser;
import web.model.Permissions;
import web.model.Roles;
import web.model.temp.SimpleUser;
import web.model.temp.VoZtree;
import web.service.AdminService;
import web.service.PermissionsService;
import web.validator.AddUserValidator;

@RequiresPermissions("admin:admin:view")
public class AdminController extends BaseController {
	private static final AdminService service = new AdminService();
	private static final Log LOGGER = Log.getLog(AdminController.class);
	private static PermissionsService permissionsService = new PermissionsService();

	@ClearShiro
	public void login() {
		render("login.ftl");
	}

	@Before(AdminLoginLogInterceptor.class)
	@ClearShiro
	public void loginin() {

		String username = getPara("username");
		String password = getPara("password");
		if (StringUtil.isNoneBlank(username, password)) {
			boolean res = baselogin(username, Secure.encryptPwd(password));
			if (res) {
				redirect("/admin/index");
			} else {
				sendAlert("用户名密码错误", "/admin/login");
			}
		} else {
			sendAlert("用户名密码不能为空", "/admin/login");
		}
		// 如果已经登录，则跳转到管理首页
	}

	public void index() {
		List<Permissions> permissions = buildMenu();
		setAttr("menu", permissions);
		SimpleUser usr = ShiroKit.getPrincipal();
		if (usr != null) {
			setAttr("username", usr.getUsername());
		}
		render("../index.ftl");
	}
	private List<Permissions> buildMenu() {
		List<Permissions> list = Permissions.dao.find("select * from permissions where is_show=0");
		List<Permissions> nodeList = new ArrayList<Permissions>();
		for (Permissions node1 : list) {
			boolean mark = false;
			for (Permissions node2 : list) {
				if (node1.getParentId() != null && node1.getParentId().equals(node2.getId())) {
					mark = true;
					if (node2.getChildren() == null)
						node2.setChildren(new ArrayList<Permissions>());
					if (ShiroMethod.hasPermission(node1.getPermission())) {
						node2.getChildren().add(node1);
					}
					break;
				}
			}
			if (!mark) {
				if (ShiroMethod.hasPermission(node1.getPermission())) {
					nodeList.add(node1);
				}
			}
		}
		return nodeList;

	}

	private boolean baselogin(String username, String password) {
		Subject user = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());
		token.setRememberMe(true);
		try {
			user.login(token);
			return true;
		} catch (UnknownAccountException e) {
			LOGGER.error("账号不存在：{}", e);
			sendAlert("账号不存在", "/admin/login");

		} catch (DisabledAccountException e) {
			LOGGER.error("账号未启用：{}", e);
			sendAlert("账号未启用", "/admin/login");
		} catch (IncorrectCredentialsException e) {
			LOGGER.error("密码错误：{}", e);
			sendAlert("密码错误", "/admin/login");
		} catch (RuntimeException e) {
			LOGGER.error("未知错误,请联系管理员：{}", e);
			sendAlert("未知错误,请联系管理员", "/admin/login");
		}
		return false;
	}

	public void loginout() {
		Subject currentUser = SecurityUtils.getSubject();
		try {
			currentUser.logout();
			this.removeSessionAttr("user");
			this.redirect("/admin/login");
		} catch (SessionException ise) {
			LOGGER.debug("Encountered session exception during logout.  This can generally safely be ignored.", ise);
		} catch (Exception e) {
			LOGGER.debug("登出发生错误", e);
		}
	}

	@RequiresPermissions("admin:admin:list")
	public void list() {
		List<AdminUser> users = service.getList();
		setAttr("users", users);
		render("list.ftl");
	}

	/**
	 * @Title: checkUserName @Description: 验证用户名唯一性 @author yyw @throws
	 */
	public void checkUserNameUnique() {
		String username = getPara("username");
		boolean returnMsg = false;
		if (StringUtil.isNotBlank(username)) {
			AdminUser user = service.getUserByName(username);
			if (user == null) {
				returnMsg = true;
			}
		}
		renderJson(returnMsg);
	}

	@Before(AddUserValidator.class)
	@RequiresPermissions("admin:admin:add")
	public void add() {
		String username = getPara("username");
		String password = getPara("password");
		AdminUser u = new AdminUser();
		u.setUsername(username);
		u.setPassword(Secure.encryptPwd(password));
		boolean r = u.save();
		if (r) {
			sendAlert("添加用户成功", "/admin/list");
		} else {
			sendAlert("添加用户失败", "/admin/list");
		}
	}

	@RequiresPermissions("admin:admin:del")
	public void del() {
		int id = getParaToInt(0, 1);
		if (id != 1) {
			boolean r = new AdminUser().deleteById(id);
			if (r) {
				// 删除缓存
				CacheKit.removeAll(Const.ADMIN_USER_CACHE);
				sendAlert("删除用户成功", "/admin/list");
			} else {
				sendAlert("删除用户失败", "/admin/list");
			}
		} else {
			sendAlert("删除用户失败", "/admin/list");
		}

	}

	@RequiresPermissions("admin:admin:perm")
	public void editperm() {
		int id = getParaToInt(0, 0);
		if (id > 0) {
			List<AdminRole> adminRoles = AdminRole.dao.find("select * from admin_role where admin_id=?", id);
			Map<Long, AdminRole> map = Maps.newHashMap();
			if (!adminRoles.isEmpty()) {
				map = Maps.uniqueIndex(adminRoles, new Function<AdminRole, Long>() {
					@Override
					public Long apply(AdminRole input) {
						return input.getRoleId();
					}
				});
			}
			setAttr("armap", map);
			List<Roles> roles = Roles.dao.find("select * from roles");
			List<VoZtree> znodes = permissionsService.getVoZtreeList();
			List<AdminPerm> adminperm = AdminPerm.dao.find("select * from admin_perm where admin_id=?", id);
			Set<Long> permIdSet = new HashSet<>();
			for (AdminPerm ap : adminperm) {
				permIdSet.add(ap.getPermId());
			}

			List<VoZtree> nodeList = new ArrayList<VoZtree>();
			for (VoZtree node1 : znodes) {
				boolean mark = false;
				if (permIdSet.contains(node1.getId())) {
					node1.setChecked(true);
				}
				for (VoZtree node2 : znodes) {
					if (node1.getPid() == node2.getId()) {
						mark = true;
						if (node2.getChildren() == null)
							node2.setChildren(new ArrayList<VoZtree>());
						node2.getChildren().add(node1);
						break;
					}
				}
				if (!mark) {
					nodeList.add(node1);
				}
			}
			setAttr("znodes", JSON.toJSONString(nodeList));
			setAttr("roles", roles);
			setAttr("adminid", id);
			render("admin_role.ftl");
		} else {
			sendAlert("提交数据出错", "/admin/list");
		}
	}

	@RequiresPermissions("admin:admin:perm")
	public void saverole() {
		JsonEntity json = new JsonEntity<>();
		int adminid = getParaToInt("adminid", 0);
		if (adminid > 0) {
			Integer[] roles = getParaValuesToInt("role");
			int i = Db.update("DELETE FROM `admin_role` WHERE `admin_id`=?", adminid);
			List<String> sqlList = new ArrayList<>();
			if (roles != null) {
				for (Integer integer : roles) {
					sqlList.add("INSERT INTO `admin_role` (`admin_id`, `role_id`) VALUES ('" + adminid + "', '"
							+ integer + "')");
				}
			}

			Db.batch(sqlList, 10);
			EhCacheKit.cleanRoleAndPerm();
			renderJson(json);
		} else {
			json.setJsonEntity(ResultCodeEnum.ERROR);
			json.setMsg("提交数据出错");
			renderJson(json);
		}
	}

	@RequiresPermissions("admin:admin:perm")
	public void saveperm() {
		int adminid = getParaToInt("adminid", 0);
		String perms = getPara("perms");
		String[] permArray = StringUtil.split(perms, ",");
		JsonEntity json = new JsonEntity<>();
		if (adminid > 0) {
			int i = Db.update("DELETE FROM `admin_perm` WHERE `admin_id`=?", adminid);
			if (permArray != null && permArray.length > 0) {
				List<String> sqlList = new ArrayList<>();
				for (String perm : permArray) {
					int p = NumberUtils.toInt(perm);
					if (p > 0) {
						sqlList.add("INSERT INTO `admin_perm` (`admin_id`, `perm_id`) VALUES ('" + adminid
								+ "', '" + p + "')");
					}
				}
				Db.batch(sqlList, 10);
				EhCacheKit.cleanRoleAndPerm();
				renderJson(json);
			} else {
				renderJson(json);
			}
		} else {
			json.setJsonEntity(ResultCodeEnum.ERROR);
			json.setMsg("用户id不能为空");
			renderJson(json);
		}
	}
}
